/**
 * 网络请求封装模块
 * @author Wu.Liang
 * @date 2025-01-21
 */

import { useAuthStore } from '@/store'
import { processQueryParams, processFormParams } from '@/utils/request'

// 基础配置
const BASE_URL = 'http://127.0.0.1:8000'
const TIMEOUT = 10000
const MAX_RETRY = 2

// 请求队列，用于Token刷新时暂停其他请求
let requestQueue = []
let isRefreshing = false

/**
 * 处理请求队列
 */
const processQueue = (error, token = null) => {
  requestQueue.forEach(({ resolve, reject }) => {
    if (error) {
      reject(error)
    } else {
      resolve(token)
    }
  })
  requestQueue = []
}

/**
 * 请求拦截器
 */
uni.addInterceptor('request', {
  invoke(args) {
    // 添加基础URL
    if (!args.url.startsWith('http')) {
      args.url = BASE_URL + args.url
    }
    
    // 添加token
    const authStore = useAuthStore()
    if (authStore.token) {
      args.header = {
        ...args.header,
        'Authorization': `Bearer ${authStore.token}`
      }
    }
    
    // 添加公共请求头
    args.header = {
      'Content-Type': 'application/json',
      'X-Requested-With': 'XMLHttpRequest',
      'X-Platform': 'mobile',
      'X-App-Version': '3.0.0',
      ...args.header
    }
    
    // 设置超时时间
    args.timeout = TIMEOUT
    
    console.log('请求拦截器:', args.url, args.data)
  },
  fail(err) {
    console.error('请求失败:', err)
    uni.showToast({
      title: '网络请求失败',
      icon: 'none'
    })
  }
})

/**
 * 响应拦截器
 */
uni.addInterceptor('request', {
  success(res) {
    console.log('响应拦截器:', res.statusCode, res.data)
    
    // 处理响应数据
    if (res.statusCode === 401) {
      const authStore = useAuthStore()
      
      // 优先使用后端返回的错误消息，如果没有则使用默认消息
      const errorMessage = res.data?.message || res.data?.msg || '登录已过期，请重新登录'
      
      // 如果是刷新Token的请求失败，直接清除认证状态
      if (res.config?.url?.includes('/auth/refresh')) {
        authStore.clearAuth()
        uni.showToast({
          title: errorMessage,
          icon: 'none'
        })
        
        setTimeout(() => {
          uni.reLaunch({
            url: '/pages/login/login'
          })
        }, 1500)
        
        return Promise.reject(new Error(errorMessage))
      }
      
      // 其他401请求，尝试刷新Token
      if (!isRefreshing) {
        isRefreshing = true
        
        authStore.refreshTokenAction()
          .then(token => {
            processQueue(null, token)
            isRefreshing = false
          })
          .catch(error => {
            processQueue(error, null)
            isRefreshing = false
            
            // 刷新失败，清除认证状态
            authStore.clearAuth()
            uni.showToast({
              title: errorMessage,
              icon: 'none'
            })
            
            setTimeout(() => {
              uni.reLaunch({
                url: '/pages/login/login'
              })
            }, 1500)
          })
      }
      
      // 将当前请求加入队列
      return new Promise((resolve, reject) => {
        requestQueue.push({ resolve, reject })
      }).then(token => {
        // 使用新token重试请求
        res.config.header.Authorization = `Bearer ${token}`
        return uni.request(res.config)
      }).catch(error => {
        return Promise.reject(error)
      })
    }
    
    if (res.statusCode >= 400) {
      // 优先使用后端返回的错误消息，如果没有则使用默认消息
      const message = res.data?.message || res.data?.msg || '请求失败'
      
      // 根据错误类型显示不同的提示
      if (res.statusCode === 403) {
        uni.showToast({
          title: '没有权限访问',
          icon: 'none'
        })
      } else if (res.statusCode === 404) {
        uni.showToast({
          title: '请求的资源不存在',
          icon: 'none'
        })
      } else if (res.statusCode === 500) {
        uni.showToast({
          title: '服务器内部错误',
          icon: 'none'
        })
      } else {
        uni.showToast({
          title: message,
          icon: 'none'
        })
      }
      
      return Promise.reject(new Error(message))
    }
    
    return res
  }
})

/**
 * 基础请求方法
 */
const request = {
  /**
   * GET请求
   * @param {string} url 请求地址
   * @param {object} data 请求参数
   * @param {object} options 其他选项
   */
  get(url, data = {}, options = {}) {
    // 处理GET请求的查询参数，过滤空值
    const filteredData = processQueryParams(data)
    return this._request('GET', url, filteredData, options)
  },
  
  /**
   * POST请求
   * @param {string} url 请求地址
   * @param {object} data 请求参数
   * @param {object} options 其他选项
   */
  post(url, data = {}, options = {}) {
    // 处理POST请求的数据，过滤空值
    const filteredData = processFormParams(data)
    return this._request('POST', url, filteredData, options)
  },
  
  /**
   * PUT请求
   * @param {string} url 请求地址
   * @param {object} data 请求参数
   * @param {object} options 其他选项
   */
  put(url, data = {}, options = {}) {
    // 处理PUT请求的数据，过滤空值
    const filteredData = processFormParams(data)
    return this._request('PUT', url, filteredData, options)
  },
  
  /**
   * DELETE请求
   * @param {string} url 请求地址
   * @param {object} data 请求参数
   * @param {object} options 其他选项
   */
  delete(url, data = {}, options = {}) {
    // 处理DELETE请求的查询参数，过滤空值
    const filteredData = processQueryParams(data)
    return this._request('DELETE', url, filteredData, options)
  },
  
  /**
   * 通用请求方法
   * @param {string} method 请求方法
   * @param {string} url 请求地址
   * @param {object} data 请求数据
   * @param {object} options 其他选项
   */
  _request(method, url, data = {}, options = {}) {
    let retryCount = 0
    
    const makeRequest = () => {
      return new Promise((resolve, reject) => {
        const requestOptions = {
          url,
          method,
          data: method === 'GET' ? data : data,
          header: options.header || {},
          timeout: options.timeout || TIMEOUT,
          success: (res) => {
            // 检查响应状态
            if (res.statusCode === 200) {
              resolve(res.data)
            } else {
              // 优先使用后端返回的错误消息，如果没有则使用默认消息
              const errorMessage = res.data?.message || res.data?.msg || '请求失败'
              reject(new Error(errorMessage))
            }
          },
          fail: (err) => {
            // 网络错误重试
            if (this._isNetworkError(err) && retryCount < MAX_RETRY) {
              retryCount++
              console.log(`网络错误，第${retryCount}次重试`)
              setTimeout(() => {
                makeRequest().then(resolve).catch(reject)
              }, 1000 * retryCount)
            } else {
              reject(err)
            }
          }
        }
        
        uni.request(requestOptions)
      })
    }
    
    return makeRequest()
  },
  
  /**
   * 判断是否为网络错误
   * @param {object} err 错误对象
   */
  _isNetworkError(err) {
    return err.errMsg && (
      err.errMsg.includes('timeout') ||
      err.errMsg.includes('fail') ||
      err.errMsg.includes('error')
    )
  },
  
  /**
   * 文件上传
   * @param {string} url 上传地址
   * @param {string} filePath 文件路径
   * @param {string} name 文件字段名
   * @param {object} formData 其他表单数据
   */
  upload(url, filePath, name = 'file', formData = {}) {
    return new Promise((resolve, reject) => {
      const authStore = useAuthStore()
      
      uni.uploadFile({
        url: BASE_URL + url,
        filePath,
        name,
        formData,
        header: {
          'Authorization': `Bearer ${authStore.token}`,
          'X-Platform': 'mobile',
          'X-App-Version': '3.0.0'
        },
        success: (res) => {
          try {
            const data = JSON.parse(res.data)
            if (data.code === 200) {
              resolve(data)
            } else {
              // 优先使用后端返回的错误消息，如果没有则使用默认消息
              const errorMessage = data.message || data.msg || '上传失败'
              reject(new Error(errorMessage))
            }
          } catch (error) {
            reject(new Error('响应数据解析失败'))
          }
        },
        fail: (err) => {
          reject(err)
        }
      })
    })
  },
  
  /**
   * 文件下载
   * @param {string} url 下载地址
   * @param {object} options 下载选项
   */
  download(url, options = {}) {
    return new Promise((resolve, reject) => {
      const authStore = useAuthStore()
      
      uni.downloadFile({
        url: BASE_URL + url,
        header: {
          'Authorization': `Bearer ${authStore.token}`,
          'X-Platform': 'mobile',
          'X-App-Version': '3.0.0'
        },
        success: (res) => {
          if (res.statusCode === 200) {
            resolve(res)
          } else {
            reject(new Error('下载失败'))
          }
        },
        fail: (err) => {
          reject(err)
        }
      })
    })
  }
}

export default request 